package com.glsc.ngateway.platform.service;


import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.RoleUrl;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.Url;
import com.glsc.ngateway.common.base.exception.PlatformException;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.RoleUrlRepo;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.UrlRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


@Service
public class UrlService {

    private UrlRepo urlRepo;
    private RoleUrlRepo roleUrlRepo;

    @Autowired
    public void setUrlRepo(UrlRepo urlRepo) {
        this.urlRepo = urlRepo;
    }

    @Autowired
    public void setRoleUrlRepo(RoleUrlRepo roleUrlRepo) {
        this.roleUrlRepo = roleUrlRepo;
    }

    @Transactional
    @CacheEvict(value="requireAuthUrlSetCache",allEntries = true)
    public void addUrl(Url url) {
        if (url.getId() != null) {
            throw PlatformException.error("新增权限不要输入id");
        }
        url = urlRepo.save(url);
        List<RoleUrl> roleUrls = roleUrlRepo.findByUrlId(url.getParentId());
        Url finalUrl = url;
        List<RoleUrl> roleUrlList = new ArrayList<>();
        roleUrls.forEach(k -> {
            RoleUrl roleUrl = new RoleUrl();
            roleUrl.setUrlId(finalUrl.getId());
            roleUrl.setRoleId(k.getRoleId());
            roleUrlList.add(roleUrl);
        });
        roleUrlRepo.saveAll(roleUrlList);
    }

    @Transactional
    @CacheEvict(value="requireAuthUrlSetCache",allEntries = true)
    public Url update(Url url) {
        if (url.getId() == null) {
            throw PlatformException.error("权限id不能为空");
        }
        Url existUrl = urlRepo.queryByIdLock(url.getId());
        if (existUrl == null) {
            throw PlatformException.error("未找到id=" + url.getId() + "的权限");
        }
        return urlRepo.save(url);
    }

    @CacheEvict(value="requireAuthUrlSetCache",allEntries = true)
    public int delete(long id) {
        return urlRepo.deleteById(id);
    }

    public Page<Url> findPage(Specification s, int page, int size) {
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "id";
        Pageable pageable = PageRequest.of(page - 1, size, direction, sort);
        return urlRepo.findAll(s, pageable);
    }

    public List<Url> findAll() {
        return urlRepo.findAll();
    }

    public List<Url> findAll(Specification s) {
        return urlRepo.findAll(s);
    }

    public Url findById(long id) {
        return urlRepo.findById(id).orElse(null);
    }

    public Url save(Url url) {
        return urlRepo.save(url);
    }

    public Set<Url> queryAllByRequireAuth(int requireAuth) {
        return urlRepo.queryAllByRequireAuth(requireAuth);
    }

    @Cacheable(cacheNames = "requireAuthUrlSetCache", key="#requireAuth")
    public Set<String> queryAllUrlsByRequireAuth(int requireAuth) {
        return urlRepo.queryAllByRequireAuth(requireAuth).stream()
                .map(url -> url.getUrl())
                .collect(Collectors.toSet());
    }

    @Transactional
    public void addRoles(List<Long> authIds, List<Long> roleIds) {
        authIds.forEach(authId->{
            roleIds.forEach(id -> roleUrlRepo.addAuthRole(authId, id));
        });
    }

    @Transactional
    public void deleteRoles(List<Long> authIds, List<Long> roleIds) {
        authIds.forEach(authId->{
            roleIds.forEach(id -> roleUrlRepo.deleteAuthRole(authId, id));
        });
    }
}
